﻿using System;
using System.IO;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.Generic;
using System.Configuration;
using System.Windows.Forms;
using ZEntity.Data.Helper;
using ZEntity.WMain.Entity;
using System.Threading;

namespace ZEntity.WMain
{
    public partial class Form1 : Form
    {
        private string serverName = string.Empty;
        private string userName = string.Empty;
        private string password = string.Empty;
        private string creator = string.Empty;
        private string assembly = string.Empty;
        private string savePath = string.Empty;
        private int tableCount = 0;
        private Thread threadGenerateEntityClass;
        private delegate void DelegateChangeBtnGenerateClassEnableState(bool isEnabled);
        private static string connStringPattern = "Data Source={0}; Initial Catalog={1}; User Id={2}; Password={3};";

        #region private methods

        /// <summary>
        /// 初始化控件显示保存连接
        /// </summary>
        private void InitCustomControllers() {
            serverName = ConvertUtils.ToString(ConfigurationManager.AppSettings.Get("ServerName"));
            userName = ConvertUtils.ToString(ConfigurationManager.AppSettings.Get("UserName"));
            password = ConvertUtils.ToString(ConfigurationManager.AppSettings.Get("Password"));
            creator = ConvertUtils.ToString(ConfigurationManager.AppSettings.Get("Creator"));
            assembly = ConvertUtils.ToString(ConfigurationManager.AppSettings.Get("Assembly"));
            string savePathFromConfig = ConvertUtils.ToString(ConfigurationManager.AppSettings.Get("SavePath"));
            savePath = savePathFromConfig == string.Empty ? System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase : savePathFromConfig;
            txtServerName.Text = serverName;
            txtUserName.Text = userName;
            txtPassword.Text = password;
            txtCreator.Text = creator;
            txtAssembly.Text = assembly;
            txtSaveFolder.Text = savePath;
        }

        /// <summary>
        /// 保存连接
        /// </summary>
        private void SaveDBConnection() {
            serverName = txtServerName.Text.Trim();
            userName = txtUserName.Text.Trim();
            password = txtPassword.Text.Trim();
            Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (!appConfig.AppSettings.Settings.AllKeys.Contains<string>("ServerName")) {
                appConfig.AppSettings.Settings.Add("ServerName", serverName);
            } else {
                appConfig.AppSettings.Settings["ServerName"].Value = serverName;
            }

            if (!appConfig.AppSettings.Settings.AllKeys.Contains<string>("UserName")) {
                appConfig.AppSettings.Settings.Add("UserName", userName);
            } else {
                appConfig.AppSettings.Settings["UserName"].Value = userName;
            }

            if (!appConfig.AppSettings.Settings.AllKeys.Contains<string>("Password")) {
                appConfig.AppSettings.Settings.Add("Password", password);
            } else {
                appConfig.AppSettings.Settings["Password"].Value = password;
            }
            appConfig.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }

        /// <summary>
        /// 保存附加配置（创建人、程序集、目录）
        /// </summary>
        private void SaveGenerationConfig() {
            creator = txtCreator.Text.Trim();
            assembly = txtAssembly.Text.Trim();
            savePath = txtSaveFolder.Text.Trim();
            Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (!appConfig.AppSettings.Settings.AllKeys.Contains<string>("Creator")) {
                appConfig.AppSettings.Settings.Add("Creator", creator);
            } else {
                appConfig.AppSettings.Settings["Creator"].Value = creator;
            }

            if (!appConfig.AppSettings.Settings.AllKeys.Contains<string>("Assembly")) {
                appConfig.AppSettings.Settings.Add("Assembly", assembly);
            } else {
                appConfig.AppSettings.Settings["Assembly"].Value = assembly;
            }

            if (!appConfig.AppSettings.Settings.AllKeys.Contains<string>("SavePath")) {
                appConfig.AppSettings.Settings.Add("SavePath", savePath);
            } else {
                appConfig.AppSettings.Settings["SavePath"].Value = savePath;
            }

            appConfig.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }

        #endregion

        #region thread delegates

        /// <summary>
        /// 改变生成实体类按钮的Enable属性
        /// </summary>
        /// <param name="isEnabled"></param>
        private void ChangeBtnGenerateClassEnableState(bool isEnabled) {            
            if (btnStartGenerate.InvokeRequired) {
                DelegateChangeBtnGenerateClassEnableState d = new DelegateChangeBtnGenerateClassEnableState(ChangeBtnGenerateClassEnableState);
                btnStartGenerate.Invoke(d, isEnabled);
            } else {
                btnStartGenerate.Enabled = isEnabled;
            }
        }

        #endregion

        public Form1() {
            InitializeComponent();

            //初始化控件显示保存连接
            InitCustomControllers();
        }

        private void btnConnectDB_Click(object sender, EventArgs e) {
            //测试
            


            //保存连接
            SaveDBConnection();
            IList<string> dbNameList = new List<string>();
            try {
                string connString = string.Format(connStringPattern, serverName, "master", userName, password);
                Models.SetConn(connString);
                dbNameList = Models.GetAllDBs();
            } catch {
                MessageBox.Show("数据库连接失败！");
            }
            lstDBs.DataSource = dbNameList;
        }

        /// <summary>
        /// 选择某数据库操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnConnectSelDB_Click(object sender, EventArgs e) {
            tabPage.SelectedTab = tabPage2;
            string selectedDBName = lstDBs.SelectedItem.ToString();
            string connString = string.Format(connStringPattern, serverName, selectedDBName, userName, password);
            Models.SetConn(connString);
            IList<string> tableNameList = Models.GetAllTabels();
            tableCount = tableNameList.Count;
            lstTables.DataSource = tableNameList;
        }     

        /// <summary>
        /// 全选复选框选中、反选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chkSelectAllTables_CheckedChanged(object sender, EventArgs e) {
            if (lstTables.Items.Count == 0)
                return;
                
            if (chkSelectAllTables.Checked) {
                for (int i = 0; i < lstTables.Items.Count; i++) {
                    lstTables.SetSelected(i, true);
                }
            } else {
                lstTables.ClearSelected();
                lstTables.SetSelected(0, true);
            }
        }

        /// <summary>
        /// 点击开始生成类
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStartGenerate_Click(object sender, EventArgs e) {
            if (lstTables.Items.Count == 0)
                return;
            threadGenerateEntityClass = new Thread(new ThreadStart(GenerateEntityClassFile));
            threadGenerateEntityClass.Start();
            ChangeBtnGenerateClassEnableState(false);
        }

        private void GenerateEntityClassFile() {
            IList<TableColumnInfo> list;
            try {
                foreach (object obj in lstTables.SelectedItems) {
                    list = Models.GetAllColumnInfoByTableName(obj.ToString());

                    //保存单一文件
                    SaveGeneratedFiles(obj.ToString() + ".cs", list);
                }
            } catch (Exception ex) {
                MessageBox.Show(string.Format("详细信息： {0}\n{1}", ex.Message, ex.StackTrace), "保存失败");
            }

            //保存附加配置（创建人、程序集、目录）
            SaveGenerationConfig();

            MessageBox.Show("文件保存成功！");
            ChangeBtnGenerateClassEnableState(true);
        }

        /// <summary>
        /// 保存单一文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        private void SaveGeneratedFiles(string fileName, IList<TableColumnInfo> list) {
            string filePath = savePath + "/" + fileName;
            string tableName = list[0].TableName;
            string tableDescription = list[0].TableDescription;
            string columnNameFirstLetter = string.Empty;
            string columnNameRestLetter = string.Empty;
            string privateFieldName = string.Empty;
            string publicPropertyName = string.Empty;
            string dbTypeName = string.Empty;
            string entityTypeName = string.Empty;
            StringBuilder sb = new StringBuilder();  
            
            //文件注释
            sb.AppendLine("/********************************************************************"); 
            sb.AppendFormat("** @创建人: {0}\r\n", creator);
            sb.AppendLine("** @创建日期: " + DateTime.Now);
            sb.AppendLine("** @功能描述:");
            sb.AppendLine("** @最终修改日期: " + DateTime.Now);
            sb.AppendFormat("** @最终修改人: {0}\r\n", creator);
            sb.AppendLine("********************************************************************/");
            sb.AppendLine("");

            //命名空间定义开始
            sb.AppendLine("using System;");
            if (chkIsAttachAttribute.Checked) {
                sb.AppendLine("using System.Data;");
                sb.AppendLine("using ZEntity.Data.ORM;");
            }
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("");
            sb.AppendFormat("namespace {0}\r\n", assembly);
            sb.AppendLine("{");

            //类定义开始        
            sb.AppendLine("\t/// <summary>");
            sb.AppendFormat("\t/// {0}\r\n", tableDescription);
            sb.AppendLine("\t/// <summary>");
            sb.AppendLine("\t[Serializable]");
            if (chkIsAttachAttribute.Checked) {
                sb.AppendFormat("\t[DataTable(\"{0}\")]\r\n", tableName);
            }
            sb.AppendFormat("\tpublic class {0}\r\n", tableName);
            sb.AppendLine("\t{");

            //属性     
            TableColumnInfo item;
            int columnListCount = list.Count;
            for (int i = 0; i < columnListCount; i++) {
                item = list[i];            
                columnNameFirstLetter = item.ColumnName == string.Empty ? "" : item.ColumnName.Substring(0,1);
                columnNameRestLetter = item.ColumnName.Length <= 1 ? "" : item.ColumnName.Substring(1);
                privateFieldName = columnNameFirstLetter.ToLower() + columnNameRestLetter;
                publicPropertyName = columnNameFirstLetter.ToUpper() + columnNameRestLetter;
                GetDBTypeString(item.TypeName, out dbTypeName, out entityTypeName);
                sb.AppendFormat("\t\tprivate {0} {1};\r\n", entityTypeName, privateFieldName);
                sb.AppendLine("\t\t/// <summary>");
                sb.AppendFormat("\t\t/// {0}\r\n", item.Description);
                sb.AppendLine("\t\t/// <summary>");
                if (chkIsAttachAttribute.Checked) {
                    sb.AppendFormat("\t\t[{0}(\"{1}\", Type = SqlDbType.{2}, Length = {3}, Nullable = {4})]\r\n",
                        item.IsPrimaryKey ? "KeyField" : "DataField", item.ColumnName, dbTypeName, item.Length, item.Nullable.ToString().ToLower());
                }
                sb.AppendFormat("\t\tpublic {0} {1}\r\n", entityTypeName, publicPropertyName);
                sb.AppendLine("\t\t{");
                sb.AppendFormat("\t\t\tget {{ return {0}; }}\r\n", privateFieldName);
                sb.AppendFormat("\t\t\tset {{ {0} = value; }}\r\n", privateFieldName);
                sb.AppendLine("\t\t}");
                if (i != columnListCount - 1) {
                    sb.AppendLine("");
                }                
            }            

            //类定义结束
            sb.AppendLine("\t}");
            //命名空间定义结束
            sb.AppendLine("}");

            //写文件
            FileStream fs = new FileStream(filePath, FileMode.Create);
            StreamWriter sw = new StreamWriter(fs);
            sw.Write(sb.ToString());
            sw.Flush();
            sw.Close();
            fs.Close();
        }

        /// <summary>
        /// Ctol + A 全选表 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lstTables_KeyUp(object sender, KeyEventArgs e) {
            if (e.Control && e.KeyCode == Keys.A) {
                for (int i = 0; i < lstTables.Items.Count; i++) {
                    lstTables.SetSelected(i, true);
                }
            }
        }

        /// <summary>
        /// 选择表状态改变
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lstTables_SelectedIndexChanged(object sender, EventArgs e) {
            if (lstTables.SelectedItems.Count == tableCount) {
                chkSelectAllTables.Checked = true;
            } else {
                chkSelectAllTables.Checked = false;
            }
        }

        /// <summary>
        /// 选择目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSelSaveFolder_Click(object sender, EventArgs e) {
            if (fBrowser.ShowDialog() == DialogResult.OK) {
                if (fBrowser.SelectedPath.Trim() != "")
                    savePath = txtSaveFolder.Text = fBrowser.SelectedPath.Trim();
            }
        }

        /// <summary>
        /// 获取 SqlDbType 名称及 .net数据类型名称
        /// </summary>
        /// <param name="dbTypeName"></param>
        /// <returns></returns>
        private void GetDBTypeString(string dbTypeRawName, out string dbTypeName, out string entityTypeName) {
            dbTypeName = string.Empty;
            entityTypeName = string.Empty;
            foreach (string name in Enum.GetNames(typeof(SqlDbType))) {
                if (dbTypeRawName == name.ToLower()) {
                    dbTypeName = name;
                    break;
                }
            }
            entityTypeName = ConvertUtils.ConvertSqlDbTypeToEntityType(dbTypeName);
        }
    }
}
